﻿/*
 * Almathy Center - MainWindow.xaml.cs
 * Copyright (C) 2011 Christophe LEMOINE
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * */
using System;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

namespace AlmathyCenter
{

    /// <summary>
    /// Logique d'interaction pour MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        private Datas.Vcard vCard = null;
        private agsXMPP.XmppClientConnection xmpp = null;
        private Datas.AutoCompleteAccount account = null;
        private string oldStatusMessage = string.Empty;
        private Datas.KeyboardHook kHook = null;
        private Datas.MouseHook mHook = null;
        private DateTime lastInputActivity = DateTime.Now;
        private bool isIdle = false;
        private Timer activityTimer = null;
        private string statusMessage = string.Empty;

        public MainWindow(agsXMPP.XmppClientConnection xmppc, Datas.AutoCompleteAccount accountc, Datas.Vcard vcardc)
        {
            InitializeComponent();
            this.Left = (SystemParameters.PrimaryScreenWidth / 2) - (this.Width / 2);
            this.Top = (SystemParameters.PrimaryScreenHeight / 2) - (this.Height / 2);
            xmpp = xmppc;
            account = accountc;
            vCard = vcardc;
            this.Title = "Almathy Center - " + ((vCard.Fullname != string.Empty) ? vCard.Fullname : ((vCard.Nickname != string.Empty) ? vCard.Nickname : account.Jid.ToString()));
            StatusMessage.Text = account.StatusMessage;
            StatusBox.SelectedIndex = account.Status;
            ActivityBox.SelectedIndex = account.Activity;
            UpdateStatus();
            MoodBox.SelectedIndex = account.Mood;
            if (StatusMessage.Text.Trim() == string.Empty && StatusMessage.IsReadOnly)
            {
                StatusMessage.Tag = "empty";
                StatusMessage.Text = StatusMessage.ToolTip.ToString();
                StatusMessage.Foreground = System.Windows.Media.Brushes.Gray;
            }
            else if (StatusMessage.Text.Trim() != string.Empty && StatusMessage.IsReadOnly)
            {
                StatusMessage.Tag = "full";
                StatusMessage.Foreground = System.Windows.Media.Brushes.White;
            }
            kHook = new Datas.KeyboardHook();
            kHook.KeyPressDetected += new Datas.KeyboardHook.KeyPressDetectedHandler(KeyPressed);
            mHook = new Datas.MouseHook();
            mHook.MouseMoveDetected += new EventHandler(MouseMoved);
            activityTimer = new Timer(15000);
            activityTimer.AutoReset = true;
            activityTimer.Elapsed += new ElapsedEventHandler(activityChecker_Elapsed);
            activityTimer.Enabled = true;
            activityTimer.Start();
          }

        private void window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            activityTimer.Stop();

            if (kHook != null)
                kHook.Dispose();

            if (mHook != null)
                mHook.Dispose();

        }

        private void LicenceClicked(object sender, RoutedEventArgs e)
        {
            LicenceWindow lw = new LicenceWindow();
            lw.ShowDialog();
        }

        private void AboutClicked(object sender, RoutedEventArgs e)
        {
            AboutWindow aw = new AboutWindow();
            aw.ShowDialog();
        }

        #region Status

        private void KeyPressed(object sender, Key e)
        {
            if (!Dispatcher.CheckAccess())
            {
                Dispatcher.Invoke(DispatcherPriority.Send, new Datas.KeyboardHook.KeyPressDetectedHandler(KeyPressed), sender, e);
                return;
            }

            lastInputActivity = DateTime.Now;
            if (isIdle)
                SetComeBack();

        }

        private void MouseMoved(object sender, EventArgs e)
        {
            if (!Dispatcher.CheckAccess())
            {
                Dispatcher.Invoke(DispatcherPriority.Send, new EventHandler(MouseMoved), sender, e);
                return;
            }

            lastInputActivity = DateTime.Now;
            if (isIdle)
                SetComeBack();

        }

        private void activityChecker_Elapsed(object sender, ElapsedEventArgs e)
        {
            if (!Dispatcher.CheckAccess())
            {
                Dispatcher.Invoke(DispatcherPriority.Send, new ElapsedEventHandler(activityChecker_Elapsed), sender, e);
                return;
            }

            if (!isIdle && account.AutoIdle)
            {
                DateTime d = DateTime.Now.Subtract(new TimeSpan(0,0,account.AutoIdleDelay));
                if(d >= lastInputActivity)
                    SetIdle();

            }
        }

        private void SetIdle()
        {
            if (!isIdle && StatusBox.SelectedIndex == 0)
            {
                isIdle = true;
                ActivityBox.SelectedIndex = 0;
                StatusBox.SelectedIndex = 1;
            }
        }

        private void SetComeBack()
        {
            if (isIdle && StatusBox.SelectedIndex == 1)
            {
                isIdle = false;
                StatusBox.SelectedIndex = 0;
            }
        }

        private void UpdateStatus()
        {
            if (xmpp != null && account != null)
            {
                agsXMPP.protocol.client.Presence p = new agsXMPP.protocol.client.Presence();
                p.From = xmpp.MyJID;
                string src = "pack://application:,,,/Resources/status_offline.png";
                switch (StatusBox.SelectedIndex)
                {
                    case 0:
                        if(ActivityBox.SelectedIndex != 0)
                            ActivityBox.SelectedIndex = 0;

                        p.Type = agsXMPP.protocol.client.PresenceType.available;
                        p.Show = agsXMPP.protocol.client.ShowType.NONE;
                        p.Status = (account.StatusMessage.Trim() != string.Empty ? account.StatusMessage.Trim() + " - " : "") + "Disponible";
                        p.XDelay = new agsXMPP.protocol.x.Delay();
                        p.XDelay.Stamp = DateTime.Now;
                        xmpp.Show = p.Show;
                        xmpp.Status = p.Status;
                        src = "pack://application:,,,/Resources/status_online.png";
                        break;
                    case 1:
                        p.Type = agsXMPP.protocol.client.PresenceType.available;
                        p.Show = agsXMPP.protocol.client.ShowType.away;
                        p.Status = (account.StatusMessage.Trim() != string.Empty ? account.StatusMessage.Trim() + " - " : "") + "Absent";
                        p.XDelay = new agsXMPP.protocol.x.Delay();
                        p.XDelay.Stamp = DateTime.Now;
                        xmpp.Show = p.Show;
                        xmpp.Status = p.Status;
                        src = "pack://application:,,,/Resources/status_online.png";
                        break;
                    case 2:
                        p.Type = agsXMPP.protocol.client.PresenceType.available;
                        p.Show = agsXMPP.protocol.client.ShowType.dnd;
                        p.Status = (account.StatusMessage.Trim() != string.Empty ? account.StatusMessage.Trim() + " - " : "") + "Occupé";
                        p.XDelay = new agsXMPP.protocol.x.Delay();
                        p.XDelay.Stamp = DateTime.Now;
                        xmpp.Show = p.Show;
                        src = "pack://application:,,,/Resources/status_online.png";
                        break;
                    case 3:
                        if (ActivityBox.SelectedIndex != 0)
                            ActivityBox.SelectedIndex = 0;

                        p.Type = agsXMPP.protocol.client.PresenceType.unavailable;
                        p.Show = agsXMPP.protocol.client.ShowType.NONE;
                        p.Status = string.Empty;
                        p.XDelay = new agsXMPP.protocol.x.Delay();
                        p.XDelay.Stamp = DateTime.Now;
                        xmpp.Show = p.Show;
                        xmpp.Status = p.Status;
                        break;
                }
                p.Nickname = new agsXMPP.protocol.extensions.nickname.Nickname(vCard.Nickname);
                agsXMPP.protocol.x.vcard_update.VcardUpdate vu = new agsXMPP.protocol.x.vcard_update.VcardUpdate();
                p.AddChild(vu);
                xmpp.Send(p);
                BitmapImage image = new BitmapImage();
                image.BeginInit();
                image.UriSource = new System.Uri(src, UriKind.RelativeOrAbsolute);
                image.EndInit();
                StatusIcon.Source = image;

                if (!isIdle)
                {
                    account.Status = StatusBox.SelectedIndex;
                }
            }
        }

        private void PresenceChanged(object sender, SelectionChangedEventArgs e)
        {
            ComboBox c = sender as ComboBox;
            string src = "pack://application:,,,/icon.ico";
            switch(c.SelectedIndex)
            {
                case 0:
                    src = "pack://application:,,,/Resources/bullet_green.png";
                    break;
                case 1:
                    src = "pack://application:,,,/Resources/bullet_orange.png";
                    break;
                case 2:
                    src = "pack://application:,,,/Resources/bullet_red.png";
                    break;
                case 3:
                    src = "pack://application:,,,/Resources/bullet_black.png";
                    break;
            }
            BitmapImage image = new BitmapImage();
            image.BeginInit();
            image.UriSource = new System.Uri(src, UriKind.RelativeOrAbsolute);
            image.EndInit();
            TaskbarOverlay.Overlay = image;
            UpdateStatus();
        }

        private void StatusMessage_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (StatusMessage.IsReadOnly)
            {
                if (StatusMessage.Tag == null || StatusMessage.Tag.ToString() == "empty")
                    StatusMessage.Text = string.Empty;

                StatusMessage.IsReadOnly = false;
                StatusMessage.Background = System.Windows.Media.Brushes.White;
                StatusMessage.Foreground = System.Windows.Media.Brushes.Black;
                StatusMessage.Cursor = Cursors.Arrow;
                StatusMessage.SelectAll();
                oldStatusMessage = string.Empty;

                if (StatusMessage.Tag != null && StatusMessage.Tag.ToString() == "full")
                    oldStatusMessage = StatusMessage.Text;
            }
        }

        private void StatusMessage_KeyUp(object sender, KeyEventArgs e)
        {
            if (!StatusMessage.IsReadOnly && (e.Key == Key.Escape || e.Key == Key.Return))
            {
                if (e.Key == Key.Escape)
                    StatusMessage.Text = oldStatusMessage;

                if (e.Key == Key.Escape || e.Key == Key.Return)
                {
                    StatusMessage.Text = StatusMessage.Text.Trim();
                    StatusMessage.IsReadOnly = true;
                    StatusMessage.Background = System.Windows.Media.Brushes.Transparent;
                    StatusMessage.Foreground = System.Windows.Media.Brushes.White;
                    StatusMessage.Cursor = Cursors.Hand;
                    account.StatusMessage = StatusMessage.Text;
                    UpdateStatus();
                    if (StatusMessage.Text.Trim() == string.Empty && StatusMessage.IsReadOnly)
                    {
                        StatusMessage.Tag = "empty";
                        StatusMessage.Text = StatusMessage.ToolTip.ToString();
                        StatusMessage.Foreground = System.Windows.Media.Brushes.Gray;
                    }
                    else if (StatusMessage.Text.Trim() != string.Empty && StatusMessage.IsReadOnly)
                    {
                        StatusMessage.Tag = "full";
                        StatusMessage.Foreground = System.Windows.Media.Brushes.White;
                    }
                    statusMessage = StatusMessage.Text;
                }
            }
        }

        private void StatusMessage_LostFocus(object sender, RoutedEventArgs e)
        {
            if (!StatusMessage.IsReadOnly)
            {
                StatusMessage.Text = oldStatusMessage;
                StatusMessage.Text = StatusMessage.Text.Trim();
                StatusMessage.IsReadOnly = true;
                StatusMessage.Background = System.Windows.Media.Brushes.Transparent;
                StatusMessage.Foreground = System.Windows.Media.Brushes.White;
                StatusMessage.Cursor = Cursors.Hand;
                account.StatusMessage = StatusMessage.Text;
                UpdateStatus();
                if (StatusMessage.Text.Trim() == string.Empty && StatusMessage.IsReadOnly)
                {
                    StatusMessage.Tag = "empty";
                    StatusMessage.Text = StatusMessage.ToolTip.ToString();
                    StatusMessage.Foreground = System.Windows.Media.Brushes.Gray;
                }
                else if (StatusMessage.Text.Trim() != string.Empty && StatusMessage.IsReadOnly)
                {
                    StatusMessage.Tag = "full";
                    StatusMessage.Foreground = System.Windows.Media.Brushes.White;
                }
                statusMessage = StatusMessage.Text;
            }
        }

        private void ActivityChanged(object sender, SelectionChangedEventArgs e)
        {
            ComboBox c = sender as ComboBox;
            string activity = string.Empty;
            string text = string.Empty;
            switch (c.SelectedIndex)
            {
                case 0:
                    StatusBox.SelectedIndex = 0;
                    break;
                case 1:
                    StatusBox.SelectedIndex = 1;
                    activity = "traveling";
                    text = "En voyage";
                    break;
                case 2:
                    StatusBox.SelectedIndex = 1;
                    activity = "scheduled_holiday";
                    text = "En vacance";
                    break;
                case 3:
                    StatusBox.SelectedIndex = 1;
                    text = "En déjeuner";
                    activity = "eating";
                    break;
                case 4:
                    StatusBox.SelectedIndex = 1;
                    activity = "sleeping";
                    text = "Au lit";
                    break;
                case 5:
                    StatusBox.SelectedIndex = 2;
                    activity = "having_appointment";
                    text = "En rendez-vous";
                    break;
                case 6:
                    StatusBox.SelectedIndex = 2;
                    activity = "in_a_meeting";
                    text = "En réunion";
                    break;
                case 7:
                    StatusBox.SelectedIndex = 2;
                    activity = "on_the_phone";
                    text = "Au téléphone";
                    break;
            }
            if (xmpp != null && account != null)
            {
                string iq = "<iq from=\"" + xmpp.MyJID + "\" type=\"set\" id=\"publish1\">";
                iq += "<pubsub xmlns=\"http://jabber.org/protocol/pubsub\"><publish node=\"http://jabber.org/protocol/activity\">";
                iq += "<item><activity xmlns=\"http://jabber.org/protocol/activity\">";
                if (activity != string.Empty)
                    iq += "<" + activity + "/><text xml:lang=\"" + xmpp.ClientLanguage + "\">" + text + "</text>";

                iq += "</activity></item>";
                iq += "</publish></pubsub>";
                iq += "</iq>";
                xmpp.Send(iq);
                account.Activity = ActivityBox.SelectedIndex;
            }
            UpdateStatus();
        }

        private void MoodChanged(object sender, SelectionChangedEventArgs e)
        {
            ComboBox c = sender as ComboBox;
            string mood = string.Empty;
            string text = string.Empty;
            switch (c.SelectedIndex)
            {
                case 1:
                    mood = "happy";
                    text = "Heureux";
                    break;
                case 2:
                    mood = "relaxed";
                    text = "Souriant";
                    break;
                case 3:
                    mood = "sarcastic";
                    text = "Tire la langue";
                    break;
                case 4:
                    mood = "happy";
                    text = "Clin d'oeil";
                    break;
                case 5:
                    mood = "playful";
                    text = "Joyeux";
                    break;
                case 6:
                    mood = "surprised";
                    text = "Surpris";
                    break;
                case 7:
                    mood = "worried";
                    text = "Pas content";
                    break;
                case 8:
                    mood = "annoyed";
                    text = "Grincheux";
                    break;
                case 9:
                    mood = "angry";
                    text = "En colère";
                    break;
            }
            if (xmpp != null && account != null)
            {
                string iq = "<iq from=\"" + xmpp.MyJID + "\" type=\"set\" id=\"publish2\">";
                iq += "<pubsub xmlns=\"http://jabber.org/protocol/pubsub\"><publish node=\"http://jabber.org/protocol/mood\">";
                iq += "<item><mood xmlns=\"http://jabber.org/protocol/mood\">";
                if (mood != string.Empty)
                    iq += "<" + mood + "/><text xml:lang=\"" + xmpp.ClientLanguage + "\">" + text + "</text>";

                iq += "</mood></item>";
                iq += "</publish></pubsub>";
                iq += "</iq>";
                xmpp.Send(iq);
                account.Mood = MoodBox.SelectedIndex;
            }
        }

        #endregion

        #region Vcard

        private void VcardIcon_MouseUp(object sender, MouseButtonEventArgs e)
        {
            vCard.RetreiveFrom(xmpp.MyJID);
            VcardWindow vw = new VcardWindow(xmpp.MyJID, vCard, true);
            if ((bool)vw.ShowDialog())
            {
                if (vw.updated)
                {
                    busyIndicator1.BusyContent = "Mise à jour de la carte de visite...";
                    busyIndicator1.IsBusy = true;
                    this.IsEnabled = false;
                    Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;
                    vw.IsEnabled = false;
                    agsXMPP.protocol.iq.vcard.Vcard vc = vCard.toVcard();
                    agsXMPP.protocol.iq.vcard.VcardIq viq = new agsXMPP.protocol.iq.vcard.VcardIq(agsXMPP.protocol.client.IqType.set, new agsXMPP.Jid(xmpp.MyJID.Bare));
                    viq.Vcard = vc;
                    xmpp.IqGrabber.SendIq(viq, new agsXMPP.IqCB(publishVcardIqResult), viq.Id);
                }
                vw.Close();
            }
        }

        private void publishVcardIqResult(object sender, agsXMPP.protocol.client.IQ iq, object data)
        {
            if (!Dispatcher.CheckAccess())
            {
                Dispatcher.Invoke(DispatcherPriority.Send, new agsXMPP.IqCB(publishVcardIqResult), sender, iq, data);
                return;
            }

            string iqID = data as string;

            busyIndicator1.IsBusy = false;
            this.IsEnabled = true;
            Mouse.OverrideCursor = null;

            if (iq.Type == agsXMPP.protocol.client.IqType.result)
            {
                this.Title = "Almathy Center - " + ((vCard.Fullname != string.Empty) ? vCard.Fullname : ((vCard.Nickname != string.Empty) ? vCard.Nickname : account.Jid.ToString()));
                UpdateStatus();
                Microsoft.Windows.Controls.MessageBox.Show("Votre carte de visite a été mise à jour.", "Almathy Center", MessageBoxButton.OK, MessageBoxImage.Information);
            }
            else
            {
                Microsoft.Windows.Controls.MessageBox.Show("Impossible d'enregistrer votre carte de visite sur le serveur '" + xmpp.Server + "'.", "Erreur", MessageBoxButton.OK, MessageBoxImage.Error);
            }

            if (xmpp.IqGrabber != null) { xmpp.IqGrabber.Remove(iqID); }
        }

        #endregion






    }

}
